/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { DataGridColumn, DataGridProps } from '../data-grid.props';
import { CellMode, UseEdit, VisualData, VisualDataCell, VisualDataStatus } from './types';
import commandsEditor from '../components/editors/commands.component';
import datePicker from '../components/editors/date-picker.component';
import textAreaEditor from '../components/editors/text-area-editor.component';
import textEditor from '../components/editors/text-editor.component';
import { ref, watch } from 'vue';

export function useEdit(props: DataGridProps): UseEdit {
    const editable = ref(props.editable);
    const editOptions = ref(props.editOption);
    const wrapContent = ref(props.rowOption?.wrapContent || false);
    const identifyField = ref(props.idField);

    watch(
        () => props.editable,
        () => {
            editable.value = props.editable;
        }
    );

    const typeToEditorName = new Map<string, string>([
        ['boolean', 'checkbox'],
        ['datetime', 'date-picker'],
        ['number', 'text-editor'],
        ['string', 'text-editor'],
        ['text', 'text-area'],
        ['commands', 'commands-editor']
    ]);

    const editorMap = new Map<string, (cell: VisualDataCell, column: DataGridColumn, visualDataRow: VisualData) => any>([
        ['checkbox', textEditor],
        ['date-picker', datePicker],
        ['text-editor', textEditor],
        ['text-area', textAreaEditor],
        ['commands-editor', commandsEditor]
    ]);

    let editingCell: VisualDataCell | null;
    let editingRow: VisualData | null;

    function getEditingSnapshot(dataIdentify: string): VisualData | null {
        if (editingRow) {
            const editingDataIdentify = editingRow.data[identifyField.value].data;
            return editingDataIdentify === dataIdentify ? editingRow : null;
        }
        return null;
    }

    function beginEditCell(cell: VisualDataCell) {
        cell.mode = CellMode.editing;
        editingCell = cell;
    }

    function endEditCell(editingCell: VisualDataCell) {
        editingCell.accept();
        editingCell.mode = CellMode.editable;
    }

    function onClickCell($event: MouseEvent, cell: VisualDataCell) {
        if (editable.value && editOptions.value.editMode === 'cell' && cell.mode === CellMode.editable && editingCell !== cell) {
            if (editingCell) {
                endEditCell(editingCell);
            }
            beginEditCell(cell);
        }
    }

    function beginEditRow(visualDataRow: VisualData) {
        Object.values(visualDataRow.data)
            .filter((cell: VisualDataCell) => cell.mode === CellMode.editable)
            .forEach((editableCell: VisualDataCell) => {
                editableCell.mode = CellMode.editing;
            });
        visualDataRow.status = VisualDataStatus.editing;
        editingRow = visualDataRow;
    }

    function endEditRow(visualDataRow: VisualData, accept: boolean) {
        Object.values(visualDataRow.data)
            .filter((cell: VisualDataCell) => cell.mode === CellMode.editing)
            .forEach((editableCell: VisualDataCell) => {
                if (accept) {
                    editableCell.accept();
                } else {
                    editableCell.cancel();
                }
                editableCell.mode = CellMode.editable;
            });
        visualDataRow.status = VisualDataStatus.initial;
        if (editingRow === visualDataRow) {
            editingRow = null;
        }
    }

    function onEditingRow(visualDataRow: VisualData) {
        if (editable.value && editOptions.value.editMode === 'row' && editingRow !== visualDataRow) {
            if (editingRow) {
                endEditRow(editingRow, false);
            }
            beginEditRow(visualDataRow);
        }
    }

    function acceptEditingRow(visualDataRow: VisualData) {
        endEditRow(visualDataRow, true);
        visualDataRow.status = VisualDataStatus.initial;
    }

    function cancelEditingRow(visualDataRow: VisualData) {
        endEditRow(visualDataRow, false);
        visualDataRow.status = VisualDataStatus.initial;
    }

    function getEditor(cell: VisualDataCell, column: DataGridColumn, visualDataRow: VisualData) {
        const fieldType = column.dataType;
        let editorName = column.editor || typeToEditorName.get(fieldType) || 'text-editor';
        if (!wrapContent.value && editorName === 'text-area') {
            editorName = 'text-editor';
        }
        const editor = editorMap.get(editorName);

        if (editor) {
            return editor(cell, column, visualDataRow);
        }
        return cell.data;
    }

    return { getEditor, onClickCell, onEditingRow, acceptEditingRow, cancelEditingRow, getEditingSnapshot };
}
